package com.ia.aistream.manager.framework.aspectj.impl;

import com.ia.aistream.common.core.domain.AjaxResult;
import com.ia.aistream.common.exception.base.BaseException;
import com.ia.aistream.common.utils.IpUtils;
import com.ia.aistream.common.utils.ServletUtils;
import com.ia.aistream.common.utils.http.HttpHelper;
import com.ia.aistream.manager.framework.aspectj.AspectManager;
import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.Set;

/**
 * aop处理内容
 *
 * @author chenjunsheng
 */
@Service
public class AspectManagerImpl implements AspectManager {

    @Override
    public Object log(ProceedingJoinPoint point) throws Throwable {
        HttpServletRequest request = ServletUtils.getRequest();
        String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
        String uri = request.getRequestURI();
        String args = this.getParameters(request);
        Object result;
        long start = System.currentTimeMillis();
        try {
            result = point.proceed();
        } catch (BaseException e) {
            HttpServletResponse response = ServletUtils.getResponse();
            long time = System.currentTimeMillis() - start;
            response.setHeader("time", String.valueOf(time));
            LoggerFactory.getLogger(point.getTarget().getClass()).warn("{} [ {} ]参数:>{} 请求体:>{} 耗时:>{} 异常信息:{}", ip, uri, args, HttpHelper.getBodyString(request), time, this.getSimpleStackTrace(e));
            throw e;
        } catch (Throwable e) {
            HttpServletResponse response = ServletUtils.getResponse();
            long time = System.currentTimeMillis() - start;
            response.setHeader("time", String.valueOf(time));
            LoggerFactory.getLogger(point.getTarget().getClass()).error("{} [ {} ]参数:>{} 请求体:>{} 耗时:>{} 异常信息:", ip, uri, args, HttpHelper.getBodyString(request), time, e);
            throw e;
        }

        long time = System.currentTimeMillis() - start;
        HttpServletResponse response = ServletUtils.getResponse();
        response.setHeader("time", String.valueOf(time));
        if (result instanceof Map) {
            LoggerFactory.getLogger(point.getTarget().getClass()).info("{} [ {} ]参数:>({}) 请求体:>{} 返回:>{} 耗时:>{}毫秒", ip, uri, args, HttpHelper.getBodyString(request), ((Map) result).get(AjaxResult.MSG_TAG), time);
        } else {
            LoggerFactory.getLogger(point.getTarget().getClass()).info("{} [ {} ]参数:>({}) 请求体:>{} 耗时:>{}毫秒", ip, uri, args, HttpHelper.getBodyString(request), time);
        }
        return result;
    }

    /**
     * 组装请求参数
     *
     * @param request
     * @return
     * @author: chenjunsheng
     * @date 2018年6月27日
     */
    private String getParameters(HttpServletRequest request) {
        Map<String, String[]> parameterMap = request.getParameterMap();
        Set<Map.Entry<String, String[]>> entrySet = parameterMap.entrySet();
        StringBuilder args = new StringBuilder();
        for (Map.Entry<String, String[]> entry : entrySet) {
            args.append(entry.getKey()).append("=").append(request.getParameter(entry.getKey())).append("&");
        }

        return args.length() <= 0 ? args.toString() : args.substring(0, args.length() - 1);
    }

    /**
     * 简化异常堆栈信息
     *
     * @param throwable
     * @return
     */
    private String getSimpleStackTrace(Throwable throwable) {
        StackTraceElement[] stackTraces = throwable.getStackTrace();
        StringBuilder stackTraceInfo = new StringBuilder();
        stackTraceInfo.append("\n");
        for (StackTraceElement element : stackTraces) {
            String tmp = element.toString();
            // 只获取指定包的下的异常堆栈跟踪信息
            if (tmp.startsWith("com.ia.aistream")) {
                stackTraceInfo.append("\r\n\tat ").append(tmp);
            }
        }

        return stackTraceInfo.toString();
    }
}
